library(phyloseq)
library(ggplot2)
library(mia)
library(patchwork)

dir <- "Q:/IPE-P-Joghurtstudie/Joghurt und Haferflocken/Analysis/GitHub_repository/IPE_yogurt_rolledOat_microbiome/"

path_analysis <- paste(dir, "DataAnalysis/Results_Main_Analysis/ResultsTaxonomy/", sep="")

source(file = paste(dir, "R functions/Utils.R", sep=""))
source(file = paste(dir, "R functions/Utils_metagenomics.R", sep=""))
source(file = paste(dir, "R functions/Utils_longitudinal.R", sep=""))
source(file = paste(dir, "R functions/Utils_crossOver.R", sep=""))
load(paste(path_analysis, "tse_allwithordination.Rdata", sep=""))
cols <- c("#017b74", "#73ffec", "#ad0053", "#ffcacf", "#ff8d3f", "#ffdf91", "#00c14e","#abffc2", "#6042ed", "#90b9ff", "#700054","#ff8bfc", "#3d8b00", "#bcff7c", "#8b3700", "#ffba91", "#ff4e2a", "#000e26", "#71a800", "#577eff", "#02d0d3", "#d00039", "#dba500", "#ac72ff", "#e0c9ff", "#002e66", "#006dbd", "#02a0c8", "#db37ec",  "#e5ffd5", "#004a20", "#637500", "#ec00bf", "#434d00","#ff77a8", "#002f17", "#f1ff4b", "#533500", "#7ea2ff", "#000d4e", "#ff41a0", "#003636", "#271800", "#E41A1C", "#377EB8", "#4DAF4A", "#984EA3", "#FF7F00", "#A65628", "#F781BF", "#FFFF00FF", "#999999")

cols_Inter_treat <- c(After.Yogurt="#7570B3", After.YogurtOatmeal="#D95F02", Before.Yogurt="#AAA8C5", Before.YogurtOatmeal="#DBB394")

cols_Inter_treat2 <- c(`After Yogurt`="#7570B3", `After Yogurt Oatmeal`="#D95F02", `Before Yogurt`="#AAA8C5", `Before Yogurt Oatmeal`="#DBB394")

cols_Participant_Id <- rep(cols, 3)
names(cols_Participant_Id) <- unique(colData(tse)[, "Participant_ID"])

Figure 1 C: Study design and abundance of yogurt species

taxa <- c("Streptococcus_thermophilus", "Lactobacillus_delbrueckii")

pp_list <- list()
pp_list2 <- list()
for(i in seq(length(taxa))){
  
  colData(tse)$abundance <- assay(tse, "relabundance")[paste("Species:", taxa[i],sep=""),]
  pp <- plot_sample_measure_CO(tse, "abundance", taxa[i],  x="Timepoint", colorInter = T, trans = "psd_log", print_table = F)  
  pp <- pp + ylab("") + ggtitle(gsub("_", " ", taxa[i]))+ 
    theme(text=element_text(size=17))
  
  pp_list[[i]] <- pp
}


wrap_plots(pp_list, nrow=1) 

ggsave("Figure1_species.png", wrap_plots(pp_list, nrow=1), height=3.5, width=14)

Figure 2 A-B: effects of intervention, UMAP plots

cols_Inter_treat2 <- c("#AAA8C5", "#7570B3", "#DBB394", "#D95F02")
pp <- plot_ordination(tse, "UMAP", sd_threshold=1.4, rank_dominance="Family")
PartHsd_UMAP <- pp$Participants_high_sd
p3 <- plot_ordination(tse, "UMAP", sd_threshold=1.4, rank_dominance="Genus")$p_topdom #comment stat_ellipse() in plot_ordination()
p4 <- pp$p_inter_treat 

p3 <- p3 + ggtitle("") + xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5) + ylim(-3, 3.2) + 
  labs(color = "Dominant Genus")+ 
   theme(text=element_text(size=15)) # Most dominant genus by sample
p4 <- p4 + ggtitle("") + xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5) + ylim(-3, 3.2) + 
  labs(color = "Intervention") + 
  scale_color_manual(name = "Intervention", values=cols_Inter_treat2, labels = c("Before Yogurt", "After Yogurt", "Before Yogurt Rolled Oats", "After Yogurt Rolled Oats"))+ 
   theme(text=element_text(size=15))
wrap_plots(p4, p3) + plot_layout(guides = "collect") + plot_annotation(tag_levels = "A")

ggsave("Figure2_UMAP.png",
       wrap_plots(p4, p3) + plot_layout(guides = "collect")+ plot_annotation(tag_levels = "A"), 
       width=20, height=8)

Table 1: Groups description

library(gtsummary)
load(file=paste(dir, "DataPreparation/Metadata/Info_participant.Rdata", sep=""))
PartiInfo <- dplyr::rename(PartiInfo, Gender=Geschlecht)
PartiInfo <- dplyr::rename(PartiInfo, Age=Alter)
var <- c("Gruppe", "Gender", "Age", "BMI")
tbl_summary(PartiInfo[, var], by=Gruppe)%>% 
  bold_labels()%>% 
  gtsummary::as_gt()%>%
  gt::tab_header(title = gt::md("Demographic characteristics in each group at baseline"))
Demographic characteristics in each group at baseline
Characteristic A
N = 53
1
B
N = 57
1
Gender

    m 26 (49%) 25 (44%)
    w 27 (51%) 32 (56%)
Age 40 (27, 52) 40 (28, 55)
BMI 23.00 (20.96, 24.94) 23.82 (21.20, 25.32)
    Unknown 2 1
1 n (%); Median (Q1, Q3)

Sup Table 1: PERMANOVA at baseline T1

colData(tse)$Period <-  case_when(colData(tse)$Timepoint %in% c("T1", "T2") ~ 0,
                     colData(tse)$Timepoint %in% c("T3", "T4") ~ 1,
                     TRUE ~ NA_real_)
colData(tse)$Period <- factor(colData(tse)$Period, levels = c("0", "1"), labels=c("Period1", "Period2"))
table(colData(tse)$Period, colData(tse)$Timepoint)
         
           T1  T2  T3  T4
  Period1 109 109   0   0
  Period2   0   0 110 110
tse_baseline <- tse[, tse$Timepoint=="T1"]

tse_genus <- agglomerateByRank(tse_baseline, rank="Genus")

colData(tse_baseline)$Prevotella_genus <- assay(tse_genus, "relabundance")["Prevotella",]
colData(tse_baseline)$Bacteroides_genus <- assay(tse_genus, "relabundance")["Bacteroides",]
colData(tse_baseline)$Ruminococcus_genus <- assay(tse_genus, "relabundance")["Ruminococcus",]
library(vegan)
set.seed(1576)
permanova_euc <- adonis2(t(assay(tse_baseline, "relabundance")) ~  Gruppe+ BMI + Alter + Geschlecht + Observed + Prevotella_genus + Bacteroides_genus + Ruminococcus_genus,
                         by = "margin", # each term analyzed individually
                         data = colData(tse_baseline),
                         method = "euclidean",
                         permutations = 9999, 
                         na.action=na.omit)
permanova_euc_df <- as.data.frame(permanova_euc)


permanova_bray <- adonis2(t(assay(tse_baseline, "relabundance")) ~  Gruppe+ BMI + Alter + Geschlecht + Observed + Prevotella_genus + Bacteroides_genus + Ruminococcus_genus ,
                          by = "margin", # each term analyzed individually
                          data = colData(tse_baseline),
                          method = "bray",
                          permutations = 9999, 
                          na.action=na.omit)
permanova_bray_df <- as.data.frame(permanova_bray)


df <- data.frame(permanova_euc_df[,"Pr(>F)", drop=F],
                 permanova_bray_df[,"Pr(>F)", drop=F])
colnames(df) <- c("euclidean", "bray")
df
                   euclidean   bray
Gruppe                0.1811 0.2791
BMI                   0.8870 0.5102
Alter                 0.3989 0.1634
Geschlecht            0.0737 0.1034
Observed              0.0001 0.0001
Prevotella_genus      0.0001 0.0001
Bacteroides_genus     0.0001 0.0001
Ruminococcus_genus    0.0002 0.0001
Residual                  NA     NA
Total                     NA     NA

permanova_bray_df
                    Df SumOfSqs      R2      F Pr(>F)    
Gruppe               1   0.2202 0.00888 1.1024 0.2791    
BMI                  1   0.1925 0.00776 0.9638 0.5102    
Alter                1   0.2422 0.00976 1.2124 0.1634    
Geschlecht           1   0.2634 0.01062 1.3187 0.1034    
Observed             1   1.2981 0.05233 6.4989 0.0001 ***
Prevotella_genus     1   1.0014 0.04037 5.0136 0.0001 ***
Bacteroides_genus    1   0.7478 0.03014 3.7439 0.0001 ***
Ruminococcus_genus   1   0.5389 0.02172 2.6978 0.0001 ***
Residual            97  19.3750 0.78101                  
Total              105  24.8076 1.00000                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
write.xlsx2( round(as.data.frame(permanova_bray), 4), "resultPERMANOVA_T1.xlsx")

Sup Figure 2: additional UMAP plots

pp <- plot_ordination(tse, "UMAP", sd_threshold=1.4, rank_dominance="Family")
PartHsd_UMAP <- pp$Participants_high_sd
p1 <- pp$p_gruppe
p5 <- pp$p_part 

p1 <- p1 + ggtitle("") + xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5) + ylim(-3, 3.2) + 
  labs(color = "Group")+ 
   theme(text=element_text(size=15)) 

p5 <- p5 + ggtitle("") + xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5) + ylim(-3, 3.2) + 
   theme(text=element_text(size=15))+ theme(legend.position = "none") 
df <- as.data.frame(cbind(reducedDim(tse, "UMAP"),colData(tse)))
p_group <-  ggplot(df, aes(x=V1, y=V2, shape = Timepoint, color=Gruppe)) + 
    geom_point(size=2, alpha=0.7, stroke = 2 ) +  
    scale_shape_manual(values = c(1, 16, 2, 17, 3))+ 
    scale_color_manual(values=c("#ad0053", "#02a0c8"))+ 
    stat_ellipse(aes(shape=NULL))+
    theme_classic()+ 
  xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5.1) + ylim(-3, 3.2) + 
  labs(color = "Group")+ 
   theme(text=element_text(size=17)) + guides(shape="none")

p_sex <-  ggplot(df, aes(x=V1, y=V2, shape = Timepoint, color=Geschlecht)) + 
    geom_point(size=2, alpha=0.7, stroke = 2 ) +  
    scale_shape_manual(values = c(1, 16, 2, 17, 3))+ 
    scale_color_manual(values=c("#017b74", "#ff8d3f"))+ 
    stat_ellipse(aes(shape=NULL))+
    theme_classic()+ 
  xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5.1) + ylim(-3, 3.2) + 
  labs(color = "Gender")+ 
   theme(text=element_text(size=17))+ guides(shape="none")

p_age <-  ggplot(df, aes(x=V1, y=V2, shape = Timepoint, color=Alter)) + 
    geom_point(size=2, alpha=0.7, stroke = 2 ) +  
    scale_shape_manual(values = c(1, 16, 2, 17, 3))+ 
    scale_color_gradientn(colours = mycolors(20))+
    theme_classic()+ 
  xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5.1) + ylim(-3, 3.2) + 
  labs(color = "Age")+ 
   theme(text=element_text(size=17))+ guides(shape="none")

p_bmi <-  ggplot(df, aes(x=V1, y=V2, shape = Timepoint, color=BMI)) + 
    geom_point(size=2, alpha=0.7, stroke = 2 ) +  
    scale_shape_manual(values = c(1, 16, 2, 17, 3))+ 
    scale_color_gradientn(colours = mycolors(20))+
    theme_classic()+ 
  xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5.1) + ylim(-3, 3.2) + 
  labs(color = "BMI")+ 
   theme(text=element_text(size=17))+ guides(shape="none")

p_richness <-  ggplot(df, aes(x=V1, y=V2, shape = Timepoint, color=Observed)) + 
    geom_point(size=2, alpha=0.7, stroke = 2 ) +  
    scale_shape_manual(values = c(1, 16, 2, 17, 3))+ 
    scale_color_gradientn(colours = mycolors(20))+
    theme_classic()+ 
  xlab("UMAP 1")+ ylab("UMAP 2") + xlim(-5,5.1) + ylim(-3, 3.2) + 
  labs(color = "Observed \nrichness")+ 
   theme(text=element_text(size=17))+ guides(shape="none")
wrap_plots(p_group, p_sex, p_age, p_bmi, p_richness, p5)

ggsave("Sup_Figure2_UMAP.png",
       wrap_plots(p_group, p_sex, p_age, p_bmi, p_richness, p5), 
       width=25, height=16)

Sup Figure 3: Relative abundance of cluster specific species

genus_multi <- c("Prevotella", "Bacteroides", "Ruminococcus", "Bifidobacterium", "Phocaeicola", "Roseburia", "Candidatus_Cibiobacter", "Lachnospiraceae_unclassified")

p_list <- list()
for(i in seq(length(genus_multi))){
genus <- genus_multi[i]
p_list[[i]] <- plot_ordination(tse, "UMAP", genus=genus)$p_1spec + 
  ggtitle(gsub("_", " ", genus), NULL) + xlab("UMAP 1")+ ylab("UMAP 2") + 
  theme(text=element_text(size=17)) + guides(shape="none")+ 
  labs(color = "relative \nabundance")
}
wrap_plots(p_list, ncol=3)

ggsave("Sup_Figure3.png",
       wrap_plots(p_list, ncol=3), 
       width=23, height=18)

Sup Figure 5: Change in alpha diversity

measures <- c("dbp", "Divergence_to_median", "Log_modulo_skewness", "Observed", "Pielou", "Shannon")
subtitle <- c("Measure of Dominance", "Measure of divergence", "Measure of rarity", "Measure of richness", "Measure of Evenness", "Measure of diversity")
trans <- c("log", rep("", 5))

pp_list <- list()
for(i in seq(length(measures))){
  pp_list[[i]] <- plot_sample_measure_CO(tse, measures[i], subtitle[i], colorInter=T, trans=trans[i], print_table=F) + ggtitle(gsub("_", " ", measures[i])) + ylab("") + 
   theme(text=element_text(size=14))
}
wrap_plots(pp_list, nrow=2) 

ggsave("Sup_Figure5.png", wrap_plots(pp_list, nrow=2), width=16, height = 8)

Sup Figure 6: Change in SCFA

load(file=paste(dir, "DataPreparation/Metabolomic/MetabolomeData.Rdata", sep=""))
measures <- c("Acetic_acid", "Butyric_acid", "Hexanoic_acid", "Isobutyric_acid", "Isovaleric_acid", "Methylbutyric_acid2", "Propionic_acid", "Valeric_acid")
measures_name <- c("Acetic acid", "Butyric acid", "Hexanoic acid", "Isobutyric acid", "Isovaleric acid", "Methylbutyric acid", "Propionic acid", "Valeric acid") 

trans <- c("sqrt", "sqrt", "psd_log", "sqrt", "sqrt", "sqrt", "sqrt", "sqrt")
names(trans) <- measures
ll_plot <- list()
for(i in seq(length(measures))){
  ll_plot[[i]] <- plot_sample_measure_CO(DATA_wide, measures[i], "", x="Treatment", colorInter = T, print_table=F, trans = trans[i]) + ggtitle(measures_name[i], subtitle = NULL)+ ylab("")+
   theme(text=element_text(size=14))
}
wrap_plots(ll_plot, nrow=3)  + plot_layout(guides = "collect") 

ggsave("Sup_Figure6.png", wrap_plots(ll_plot, nrow=2), width=16, height = 8)

Sup Figure 7: Change in Blood markers

load(paste(dir, "DataPreparation/BloodMarkers/BloodData_AllMarkers.Rdata", sep=""))
measures <- c("SCRP", "IL6", "TNFR2", "FRUC", "RAGE", "8OHdG", "zonulin") 
measures_name <- c("CRP", "Interleukin-6", "TNFR2", "Fructosamine", "sRAGE", "8-OHdG", "Zonulin") 

trans <- c("log", "log", "log", "log", "", "", "")
names(trans) <- measures
ll_plot <- list()
for(i in seq(length(measures))){
  ll_plot[[i]] <- plot_sample_measure_CO(data_merged, measures[i], "", x="Treatment", colorInter = T, print_table=F, trans = trans[i]) + ggtitle(measures_name[i], subtitle = NULL)+ ylab("")+
   theme(text=element_text(size=14))
}
wrap_plots(ll_plot, nrow=3)  + plot_layout(guides = "collect") 

ggsave("Sup_Figure7.png", wrap_plots(ll_plot, nrow=3), width=16, height = 12)
LS0tDQp0aXRsZTogIkZpZ3VyZXMgcGFwZXIiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KLS0tDQoNCg0KPHN0eWxlPg0KLm1haW4tY29udGFpbmVyIHsgd2lkdGg6IDEyMDBweDsgbWF4LXdpZHRoOjI4MDBweDt9DQo8L3N0eWxlPg0KDQoNCg0KDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkocGh5bG9zZXEpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KG1pYSkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KDQpkaXIgPC0gIlE6L0lQRS1QLUpvZ2h1cnRzdHVkaWUvSm9naHVydCB1bmQgSGFmZXJmbG9ja2VuL0FuYWx5c2lzL0dpdEh1Yl9yZXBvc2l0b3J5L0lQRV95b2d1cnRfcm9sbGVkT2F0X21pY3JvYmlvbWUvIg0KDQpwYXRoX2FuYWx5c2lzIDwtIHBhc3RlKGRpciwgIkRhdGFBbmFseXNpcy9SZXN1bHRzX01haW5fQW5hbHlzaXMvUmVzdWx0c1RheG9ub215LyIsIHNlcD0iIikNCg0Kc291cmNlKGZpbGUgPSBwYXN0ZShkaXIsICJSIGZ1bmN0aW9ucy9VdGlscy5SIiwgc2VwPSIiKSkNCnNvdXJjZShmaWxlID0gcGFzdGUoZGlyLCAiUiBmdW5jdGlvbnMvVXRpbHNfbWV0YWdlbm9taWNzLlIiLCBzZXA9IiIpKQ0Kc291cmNlKGZpbGUgPSBwYXN0ZShkaXIsICJSIGZ1bmN0aW9ucy9VdGlsc19sb25naXR1ZGluYWwuUiIsIHNlcD0iIikpDQpzb3VyY2UoZmlsZSA9IHBhc3RlKGRpciwgIlIgZnVuY3Rpb25zL1V0aWxzX2Nyb3NzT3Zlci5SIiwgc2VwPSIiKSkNCmBgYA0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpsb2FkKHBhc3RlKHBhdGhfYW5hbHlzaXMsICJ0c2VfYWxsd2l0aG9yZGluYXRpb24uUmRhdGEiLCBzZXA9IiIpKQ0KYGBgDQoNCg0KYGBge3J9DQpjb2xzIDwtIGMoIiMwMTdiNzQiLCAiIzczZmZlYyIsICIjYWQwMDUzIiwgIiNmZmNhY2YiLCAiI2ZmOGQzZiIsICIjZmZkZjkxIiwgIiMwMGMxNGUiLCIjYWJmZmMyIiwgIiM2MDQyZWQiLCAiIzkwYjlmZiIsICIjNzAwMDU0IiwiI2ZmOGJmYyIsICIjM2Q4YjAwIiwgIiNiY2ZmN2MiLCAiIzhiMzcwMCIsICIjZmZiYTkxIiwgIiNmZjRlMmEiLCAiIzAwMGUyNiIsICIjNzFhODAwIiwgIiM1NzdlZmYiLCAiIzAyZDBkMyIsICIjZDAwMDM5IiwgIiNkYmE1MDAiLCAiI2FjNzJmZiIsICIjZTBjOWZmIiwgIiMwMDJlNjYiLCAiIzAwNmRiZCIsICIjMDJhMGM4IiwgIiNkYjM3ZWMiLCAgIiNlNWZmZDUiLCAiIzAwNGEyMCIsICIjNjM3NTAwIiwgIiNlYzAwYmYiLCAiIzQzNGQwMCIsIiNmZjc3YTgiLCAiIzAwMmYxNyIsICIjZjFmZjRiIiwgIiM1MzM1MDAiLCAiIzdlYTJmZiIsICIjMDAwZDRlIiwgIiNmZjQxYTAiLCAiIzAwMzYzNiIsICIjMjcxODAwIiwgIiNFNDFBMUMiLCAiIzM3N0VCOCIsICIjNERBRjRBIiwgIiM5ODRFQTMiLCAiI0ZGN0YwMCIsICIjQTY1NjI4IiwgIiNGNzgxQkYiLCAiI0ZGRkYwMEZGIiwgIiM5OTk5OTkiKQ0KDQpjb2xzX0ludGVyX3RyZWF0IDwtIGMoQWZ0ZXIuWW9ndXJ0PSIjNzU3MEIzIiwgQWZ0ZXIuWW9ndXJ0T2F0bWVhbD0iI0Q5NUYwMiIsIEJlZm9yZS5Zb2d1cnQ9IiNBQUE4QzUiLCBCZWZvcmUuWW9ndXJ0T2F0bWVhbD0iI0RCQjM5NCIpDQoNCmNvbHNfSW50ZXJfdHJlYXQyIDwtIGMoYEFmdGVyIFlvZ3VydGA9IiM3NTcwQjMiLCBgQWZ0ZXIgWW9ndXJ0IE9hdG1lYWxgPSIjRDk1RjAyIiwgYEJlZm9yZSBZb2d1cnRgPSIjQUFBOEM1IiwgYEJlZm9yZSBZb2d1cnQgT2F0bWVhbGA9IiNEQkIzOTQiKQ0KDQpjb2xzX1BhcnRpY2lwYW50X0lkIDwtIHJlcChjb2xzLCAzKQ0KbmFtZXMoY29sc19QYXJ0aWNpcGFudF9JZCkgPC0gdW5pcXVlKGNvbERhdGEodHNlKVssICJQYXJ0aWNpcGFudF9JRCJdKQ0KYGBgDQoNCg0KDQojIEZpZ3VyZSAxIEM6IFN0dWR5IGRlc2lnbiBhbmQgYWJ1bmRhbmNlIG9mIHlvZ3VydCBzcGVjaWVzDQpgYGB7ciBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTE0fQ0KdGF4YSA8LSBjKCJTdHJlcHRvY29jY3VzX3RoZXJtb3BoaWx1cyIsICJMYWN0b2JhY2lsbHVzX2RlbGJydWVja2lpIikNCg0KcHBfbGlzdCA8LSBsaXN0KCkNCnBwX2xpc3QyIDwtIGxpc3QoKQ0KZm9yKGkgaW4gc2VxKGxlbmd0aCh0YXhhKSkpew0KICANCiAgY29sRGF0YSh0c2UpJGFidW5kYW5jZSA8LSBhc3NheSh0c2UsICJyZWxhYnVuZGFuY2UiKVtwYXN0ZSgiU3BlY2llczoiLCB0YXhhW2ldLHNlcD0iIiksXQ0KICBwcCA8LSBwbG90X3NhbXBsZV9tZWFzdXJlX0NPKHRzZSwgImFidW5kYW5jZSIsIHRheGFbaV0sICB4PSJUaW1lcG9pbnQiLCBjb2xvckludGVyID0gVCwgdHJhbnMgPSAicHNkX2xvZyIsIHByaW50X3RhYmxlID0gRikgIA0KICBwcCA8LSBwcCArIHlsYWIoIiIpICsgZ2d0aXRsZShnc3ViKCJfIiwgIiAiLCB0YXhhW2ldKSkrIA0KICAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTcpKQ0KICANCiAgcHBfbGlzdFtbaV1dIDwtIHBwDQp9DQoNCg0Kd3JhcF9wbG90cyhwcF9saXN0LCBucm93PTEpIA0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJGaWd1cmUxX3NwZWNpZXMucG5nIiwgd3JhcF9wbG90cyhwcF9saXN0LCBucm93PTEpLCBoZWlnaHQ9My41LCB3aWR0aD0xNCkNCmBgYA0KDQoNCiMgRmlndXJlIDIgQS1COiBlZmZlY3RzIG9mIGludGVydmVudGlvbiwgVU1BUCBwbG90cyANCg0KYGBge3J9DQpjb2xzX0ludGVyX3RyZWF0MiA8LSBjKCIjQUFBOEM1IiwgIiM3NTcwQjMiLCAiI0RCQjM5NCIsICIjRDk1RjAyIikNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcHAgPC0gcGxvdF9vcmRpbmF0aW9uKHRzZSwgIlVNQVAiLCBzZF90aHJlc2hvbGQ9MS40LCByYW5rX2RvbWluYW5jZT0iRmFtaWx5IikNClBhcnRIc2RfVU1BUCA8LSBwcCRQYXJ0aWNpcGFudHNfaGlnaF9zZA0KcDMgPC0gcGxvdF9vcmRpbmF0aW9uKHRzZSwgIlVNQVAiLCBzZF90aHJlc2hvbGQ9MS40LCByYW5rX2RvbWluYW5jZT0iR2VudXMiKSRwX3RvcGRvbSAjY29tbWVudCBzdGF0X2VsbGlwc2UoKSBpbiBwbG90X29yZGluYXRpb24oKQ0KcDQgPC0gcHAkcF9pbnRlcl90cmVhdCANCg0KcDMgPC0gcDMgKyBnZ3RpdGxlKCIiKSArIHhsYWIoIlVNQVAgMSIpKyB5bGFiKCJVTUFQIDIiKSArIHhsaW0oLTUsNSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiRG9taW5hbnQgR2VudXMiKSsgDQogICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE1KSkgIyBNb3N0IGRvbWluYW50IGdlbnVzIGJ5IHNhbXBsZQ0KcDQgPC0gcDQgKyBnZ3RpdGxlKCIiKSArIHhsYWIoIlVNQVAgMSIpKyB5bGFiKCJVTUFQIDIiKSArIHhsaW0oLTUsNSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiSW50ZXJ2ZW50aW9uIikgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAiSW50ZXJ2ZW50aW9uIiwgdmFsdWVzPWNvbHNfSW50ZXJfdHJlYXQyLCBsYWJlbHMgPSBjKCJCZWZvcmUgWW9ndXJ0IiwgIkFmdGVyIFlvZ3VydCIsICJCZWZvcmUgWW9ndXJ0IFJvbGxlZCBPYXRzIiwgIkFmdGVyIFlvZ3VydCBSb2xsZWQgT2F0cyIpKSsgDQogICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE1KSkNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xNSwgbWVzc2FnZT1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQp3cmFwX3Bsb3RzKHA0LCBwMykgKyBwbG90X2xheW91dChndWlkZXMgPSAiY29sbGVjdCIpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpDQpgYGANCg0KDQpgYGB7cn0NCmdnc2F2ZSgiRmlndXJlMl9VTUFQLnBuZyIsDQogICAgICAgd3JhcF9wbG90cyhwNCwgcDMpICsgcGxvdF9sYXlvdXQoZ3VpZGVzID0gImNvbGxlY3QiKSsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpLCANCiAgICAgICB3aWR0aD0yMCwgaGVpZ2h0PTgpDQpgYGANCg0KDQoNCg0KIyBUYWJsZSAxOiBHcm91cHMgZGVzY3JpcHRpb24NCmBgYHtyfQ0KbGlicmFyeShndHN1bW1hcnkpDQpgYGANCg0KYGBge3J9DQpsb2FkKGZpbGU9cGFzdGUoZGlyLCAiRGF0YVByZXBhcmF0aW9uL01ldGFkYXRhL0luZm9fcGFydGljaXBhbnQuUmRhdGEiLCBzZXA9IiIpKQ0KYGBgDQoNCmBgYHtyfQ0KUGFydGlJbmZvIDwtIGRwbHlyOjpyZW5hbWUoUGFydGlJbmZvLCBHZW5kZXI9R2VzY2hsZWNodCkNClBhcnRpSW5mbyA8LSBkcGx5cjo6cmVuYW1lKFBhcnRpSW5mbywgQWdlPUFsdGVyKQ0KYGBgDQoNCg0KYGBge3J9DQp2YXIgPC0gYygiR3J1cHBlIiwgIkdlbmRlciIsICJBZ2UiLCAiQk1JIikNCnRibF9zdW1tYXJ5KFBhcnRpSW5mb1ssIHZhcl0sIGJ5PUdydXBwZSklPiUgDQogIGJvbGRfbGFiZWxzKCklPiUgDQogIGd0c3VtbWFyeTo6YXNfZ3QoKSU+JQ0KICBndDo6dGFiX2hlYWRlcih0aXRsZSA9IGd0OjptZCgiRGVtb2dyYXBoaWMgY2hhcmFjdGVyaXN0aWNzIGluIGVhY2ggZ3JvdXAgYXQgYmFzZWxpbmUiKSkNCmBgYA0KDQojIFN1cCBUYWJsZSAxOiBQRVJNQU5PVkEgYXQgYmFzZWxpbmUgVDENCg0KYGBge3J9DQpjb2xEYXRhKHRzZSkkUGVyaW9kIDwtICBjYXNlX3doZW4oY29sRGF0YSh0c2UpJFRpbWVwb2ludCAlaW4lIGMoIlQxIiwgIlQyIikgfiAwLA0KICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSh0c2UpJFRpbWVwb2ludCAlaW4lIGMoIlQzIiwgIlQ0IikgfiAxLA0KICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX3JlYWxfKQ0KY29sRGF0YSh0c2UpJFBlcmlvZCA8LSBmYWN0b3IoY29sRGF0YSh0c2UpJFBlcmlvZCwgbGV2ZWxzID0gYygiMCIsICIxIiksIGxhYmVscz1jKCJQZXJpb2QxIiwgIlBlcmlvZDIiKSkNCnRhYmxlKGNvbERhdGEodHNlKSRQZXJpb2QsIGNvbERhdGEodHNlKSRUaW1lcG9pbnQpDQpgYGANCg0KDQpgYGB7cn0NCnRzZV9iYXNlbGluZSA8LSB0c2VbLCB0c2UkVGltZXBvaW50PT0iVDEiXQ0KDQp0c2VfZ2VudXMgPC0gYWdnbG9tZXJhdGVCeVJhbmsodHNlX2Jhc2VsaW5lLCByYW5rPSJHZW51cyIpDQoNCmNvbERhdGEodHNlX2Jhc2VsaW5lKSRQcmV2b3RlbGxhX2dlbnVzIDwtIGFzc2F5KHRzZV9nZW51cywgInJlbGFidW5kYW5jZSIpWyJQcmV2b3RlbGxhIixdDQpjb2xEYXRhKHRzZV9iYXNlbGluZSkkQmFjdGVyb2lkZXNfZ2VudXMgPC0gYXNzYXkodHNlX2dlbnVzLCAicmVsYWJ1bmRhbmNlIilbIkJhY3Rlcm9pZGVzIixdDQpjb2xEYXRhKHRzZV9iYXNlbGluZSkkUnVtaW5vY29jY3VzX2dlbnVzIDwtIGFzc2F5KHRzZV9nZW51cywgInJlbGFidW5kYW5jZSIpWyJSdW1pbm9jb2NjdXMiLF0NCmBgYA0KDQpgYGB7ciBwYWdlZC5wcmludD1GQUxTRX0NCmxpYnJhcnkodmVnYW4pDQpzZXQuc2VlZCgxNTc2KQ0KcGVybWFub3ZhX2V1YyA8LSBhZG9uaXMyKHQoYXNzYXkodHNlX2Jhc2VsaW5lLCAicmVsYWJ1bmRhbmNlIikpIH4gIEdydXBwZSsgQk1JICsgQWx0ZXIgKyBHZXNjaGxlY2h0ICsgT2JzZXJ2ZWQgKyBQcmV2b3RlbGxhX2dlbnVzICsgQmFjdGVyb2lkZXNfZ2VudXMgKyBSdW1pbm9jb2NjdXNfZ2VudXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAibWFyZ2luIiwgIyBlYWNoIHRlcm0gYW5hbHl6ZWQgaW5kaXZpZHVhbGx5DQogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbERhdGEodHNlX2Jhc2VsaW5lKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiZXVjbGlkZWFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBwZXJtdXRhdGlvbnMgPSA5OTk5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICBuYS5hY3Rpb249bmEub21pdCkNCnBlcm1hbm92YV9ldWNfZGYgPC0gYXMuZGF0YS5mcmFtZShwZXJtYW5vdmFfZXVjKQ0KDQoNCnBlcm1hbm92YV9icmF5IDwtIGFkb25pczIodChhc3NheSh0c2VfYmFzZWxpbmUsICJyZWxhYnVuZGFuY2UiKSkgfiAgR3J1cHBlKyBCTUkgKyBBbHRlciArIEdlc2NobGVjaHQgKyBPYnNlcnZlZCArIFByZXZvdGVsbGFfZ2VudXMgKyBCYWN0ZXJvaWRlc19nZW51cyArIFJ1bWlub2NvY2N1c19nZW51cyAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIm1hcmdpbiIsICMgZWFjaCB0ZXJtIGFuYWx5emVkIGluZGl2aWR1YWxseQ0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY29sRGF0YSh0c2VfYmFzZWxpbmUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYnJheSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHBlcm11dGF0aW9ucyA9IDk5OTksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5hY3Rpb249bmEub21pdCkNCnBlcm1hbm92YV9icmF5X2RmIDwtIGFzLmRhdGEuZnJhbWUocGVybWFub3ZhX2JyYXkpDQoNCg0KZGYgPC0gZGF0YS5mcmFtZShwZXJtYW5vdmFfZXVjX2RmWywiUHIoPkYpIiwgZHJvcD1GXSwNCiAgICAgICAgICAgICAgICAgcGVybWFub3ZhX2JyYXlfZGZbLCJQcig+RikiLCBkcm9wPUZdKQ0KY29sbmFtZXMoZGYpIDwtIGMoImV1Y2xpZGVhbiIsICJicmF5IikNCmRmDQpgYGAgIA0KDQpgYGANCiAgICAgICAgICAgICAgICAgICBldWNsaWRlYW4gICBicmF5DQpHcnVwcGUgICAgICAgICAgICAgICAgMC4xODExIDAuMjc5MQ0KQk1JICAgICAgICAgICAgICAgICAgIDAuODg3MCAwLjUxMDINCkFsdGVyICAgICAgICAgICAgICAgICAwLjM5ODkgMC4xNjM0DQpHZXNjaGxlY2h0ICAgICAgICAgICAgMC4wNzM3IDAuMTAzNA0KT2JzZXJ2ZWQgICAgICAgICAgICAgIDAuMDAwMSAwLjAwMDENClByZXZvdGVsbGFfZ2VudXMgICAgICAwLjAwMDEgMC4wMDAxDQpCYWN0ZXJvaWRlc19nZW51cyAgICAgMC4wMDAxIDAuMDAwMQ0KUnVtaW5vY29jY3VzX2dlbnVzICAgIDAuMDAwMiAwLjAwMDENClJlc2lkdWFsICAgICAgICAgICAgICAgICAgTkEgICAgIE5BDQpUb3RhbCAgICAgICAgICAgICAgICAgICAgIE5BICAgICBOQQ0KDQpwZXJtYW5vdmFfYnJheV9kZg0KICAgICAgICAgICAgICAgICAgICBEZiBTdW1PZlNxcyAgICAgIFIyICAgICAgRiBQcig+RikgICAgDQpHcnVwcGUgICAgICAgICAgICAgICAxICAgMC4yMjAyIDAuMDA4ODggMS4xMDI0IDAuMjc5MSAgICANCkJNSSAgICAgICAgICAgICAgICAgIDEgICAwLjE5MjUgMC4wMDc3NiAwLjk2MzggMC41MTAyICAgIA0KQWx0ZXIgICAgICAgICAgICAgICAgMSAgIDAuMjQyMiAwLjAwOTc2IDEuMjEyNCAwLjE2MzQgICAgDQpHZXNjaGxlY2h0ICAgICAgICAgICAxICAgMC4yNjM0IDAuMDEwNjIgMS4zMTg3IDAuMTAzNCAgICANCk9ic2VydmVkICAgICAgICAgICAgIDEgICAxLjI5ODEgMC4wNTIzMyA2LjQ5ODkgMC4wMDAxICoqKg0KUHJldm90ZWxsYV9nZW51cyAgICAgMSAgIDEuMDAxNCAwLjA0MDM3IDUuMDEzNiAwLjAwMDEgKioqDQpCYWN0ZXJvaWRlc19nZW51cyAgICAxICAgMC43NDc4IDAuMDMwMTQgMy43NDM5IDAuMDAwMSAqKioNClJ1bWlub2NvY2N1c19nZW51cyAgIDEgICAwLjUzODkgMC4wMjE3MiAyLjY5NzggMC4wMDAxICoqKg0KUmVzaWR1YWwgICAgICAgICAgICA5NyAgMTkuMzc1MCAwLjc4MTAxICAgICAgICAgICAgICAgICAgDQpUb3RhbCAgICAgICAgICAgICAgMTA1ICAyNC44MDc2IDEuMDAwMDAgICAgICAgICAgICAgICAgICANCi0tLQ0KU2lnbmlmLiBjb2RlczogIDAg4oCYKioq4oCZIDAuMDAxIOKAmCoq4oCZIDAuMDEg4oCYKuKAmSAwLjA1IOKAmC7igJkgMC4xIOKAmCDigJkgMQ0KYGBgDQoNCg0KDQpgYGB7cn0NCndyaXRlLnhsc3gyKCByb3VuZChhcy5kYXRhLmZyYW1lKHBlcm1hbm92YV9icmF5KSwgNCksICJyZXN1bHRQRVJNQU5PVkFfVDEueGxzeCIpDQpgYGANCg0KDQoNCg0KIyBTdXAgRmlndXJlIDI6IGFkZGl0aW9uYWwgVU1BUCBwbG90cw0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcHAgPC0gcGxvdF9vcmRpbmF0aW9uKHRzZSwgIlVNQVAiLCBzZF90aHJlc2hvbGQ9MS40LCByYW5rX2RvbWluYW5jZT0iRmFtaWx5IikNClBhcnRIc2RfVU1BUCA8LSBwcCRQYXJ0aWNpcGFudHNfaGlnaF9zZA0KcDEgPC0gcHAkcF9ncnVwcGUNCnA1IDwtIHBwJHBfcGFydCANCg0KcDEgPC0gcDEgKyBnZ3RpdGxlKCIiKSArIHhsYWIoIlVNQVAgMSIpKyB5bGFiKCJVTUFQIDIiKSArIHhsaW0oLTUsNSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiR3JvdXAiKSsgDQogICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE1KSkgDQoNCnA1IDwtIHA1ICsgZ2d0aXRsZSgiIikgKyB4bGFiKCJVTUFQIDEiKSsgeWxhYigiVU1BUCAyIikgKyB4bGltKC01LDUpICsgeWxpbSgtMywgMy4yKSArIA0KICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNSkpKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIA0KYGBgDQoNCmBgYHtyfQ0KZGYgPC0gYXMuZGF0YS5mcmFtZShjYmluZChyZWR1Y2VkRGltKHRzZSwgIlVNQVAiKSxjb2xEYXRhKHRzZSkpKQ0KcF9ncm91cCA8LSAgZ2dwbG90KGRmLCBhZXMoeD1WMSwgeT1WMiwgc2hhcGUgPSBUaW1lcG9pbnQsIGNvbG9yPUdydXBwZSkpICsgDQogICAgZ2VvbV9wb2ludChzaXplPTIsIGFscGhhPTAuNywgc3Ryb2tlID0gMiApICsgIA0KICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDE2LCAyLCAxNywgMykpKyANCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNhZDAwNTMiLCAiIzAyYTBjOCIpKSsgDQogICAgc3RhdF9lbGxpcHNlKGFlcyhzaGFwZT1OVUxMKSkrDQogICAgdGhlbWVfY2xhc3NpYygpKyANCiAgeGxhYigiVU1BUCAxIikrIHlsYWIoIlVNQVAgMiIpICsgeGxpbSgtNSw1LjEpICsgeWxpbSgtMywgMy4yKSArIA0KICBsYWJzKGNvbG9yID0gIkdyb3VwIikrIA0KICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNykpICsgZ3VpZGVzKHNoYXBlPSJub25lIikNCg0KcF9zZXggPC0gIGdncGxvdChkZiwgYWVzKHg9VjEsIHk9VjIsIHNoYXBlID0gVGltZXBvaW50LCBjb2xvcj1HZXNjaGxlY2h0KSkgKyANCiAgICBnZW9tX3BvaW50KHNpemU9MiwgYWxwaGE9MC43LCBzdHJva2UgPSAyICkgKyAgDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMTYsIDIsIDE3LCAzKSkrIA0KICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAxN2I3NCIsICIjZmY4ZDNmIikpKyANCiAgICBzdGF0X2VsbGlwc2UoYWVzKHNoYXBlPU5VTEwpKSsNCiAgICB0aGVtZV9jbGFzc2ljKCkrIA0KICB4bGFiKCJVTUFQIDEiKSsgeWxhYigiVU1BUCAyIikgKyB4bGltKC01LDUuMSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiR2VuZGVyIikrIA0KICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNykpKyBndWlkZXMoc2hhcGU9Im5vbmUiKQ0KDQpwX2FnZSA8LSAgZ2dwbG90KGRmLCBhZXMoeD1WMSwgeT1WMiwgc2hhcGUgPSBUaW1lcG9pbnQsIGNvbG9yPUFsdGVyKSkgKyANCiAgICBnZW9tX3BvaW50KHNpemU9MiwgYWxwaGE9MC43LCBzdHJva2UgPSAyICkgKyAgDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMTYsIDIsIDE3LCAzKSkrIA0KICAgIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gbXljb2xvcnMoMjApKSsNCiAgICB0aGVtZV9jbGFzc2ljKCkrIA0KICB4bGFiKCJVTUFQIDEiKSsgeWxhYigiVU1BUCAyIikgKyB4bGltKC01LDUuMSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiQWdlIikrIA0KICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNykpKyBndWlkZXMoc2hhcGU9Im5vbmUiKQ0KDQpwX2JtaSA8LSAgZ2dwbG90KGRmLCBhZXMoeD1WMSwgeT1WMiwgc2hhcGUgPSBUaW1lcG9pbnQsIGNvbG9yPUJNSSkpICsgDQogICAgZ2VvbV9wb2ludChzaXplPTIsIGFscGhhPTAuNywgc3Ryb2tlID0gMiApICsgIA0KICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDE2LCAyLCAxNywgMykpKyANCiAgICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IG15Y29sb3JzKDIwKSkrDQogICAgdGhlbWVfY2xhc3NpYygpKyANCiAgeGxhYigiVU1BUCAxIikrIHlsYWIoIlVNQVAgMiIpICsgeGxpbSgtNSw1LjEpICsgeWxpbSgtMywgMy4yKSArIA0KICBsYWJzKGNvbG9yID0gIkJNSSIpKyANCiAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTcpKSsgZ3VpZGVzKHNoYXBlPSJub25lIikNCg0KcF9yaWNobmVzcyA8LSAgZ2dwbG90KGRmLCBhZXMoeD1WMSwgeT1WMiwgc2hhcGUgPSBUaW1lcG9pbnQsIGNvbG9yPU9ic2VydmVkKSkgKyANCiAgICBnZW9tX3BvaW50KHNpemU9MiwgYWxwaGE9MC43LCBzdHJva2UgPSAyICkgKyAgDQogICAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMTYsIDIsIDE3LCAzKSkrIA0KICAgIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzID0gbXljb2xvcnMoMjApKSsNCiAgICB0aGVtZV9jbGFzc2ljKCkrIA0KICB4bGFiKCJVTUFQIDEiKSsgeWxhYigiVU1BUCAyIikgKyB4bGltKC01LDUuMSkgKyB5bGltKC0zLCAzLjIpICsgDQogIGxhYnMoY29sb3IgPSAiT2JzZXJ2ZWQgXG5yaWNobmVzcyIpKyANCiAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTcpKSsgZ3VpZGVzKHNoYXBlPSJub25lIikNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTE2LCBmaWcud2lkdGg9MjAsIG1lc3NhZ2U9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0Kd3JhcF9wbG90cyhwX2dyb3VwLCBwX3NleCwgcF9hZ2UsIHBfYm1pLCBwX3JpY2huZXNzLCBwNSkNCmBgYA0KDQoNCg0KYGBge3J9DQpnZ3NhdmUoIlN1cF9GaWd1cmUyX1VNQVAucG5nIiwNCiAgICAgICB3cmFwX3Bsb3RzKHBfZ3JvdXAsIHBfc2V4LCBwX2FnZSwgcF9ibWksIHBfcmljaG5lc3MsIHA1KSwgDQogICAgICAgd2lkdGg9MjUsIGhlaWdodD0xNikNCmBgYA0KDQoNCg0KDQojIFN1cCBGaWd1cmUgMzogUmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGNsdXN0ZXIgc3BlY2lmaWMgc3BlY2llcw0KDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmdlbnVzX211bHRpIDwtIGMoIlByZXZvdGVsbGEiLCAiQmFjdGVyb2lkZXMiLCAiUnVtaW5vY29jY3VzIiwgIkJpZmlkb2JhY3Rlcml1bSIsICJQaG9jYWVpY29sYSIsICJSb3NlYnVyaWEiLCAiQ2FuZGlkYXR1c19DaWJpb2JhY3RlciIsICJMYWNobm9zcGlyYWNlYWVfdW5jbGFzc2lmaWVkIikNCg0KcF9saXN0IDwtIGxpc3QoKQ0KZm9yKGkgaW4gc2VxKGxlbmd0aChnZW51c19tdWx0aSkpKXsNCmdlbnVzIDwtIGdlbnVzX211bHRpW2ldDQpwX2xpc3RbW2ldXSA8LSBwbG90X29yZGluYXRpb24odHNlLCAiVU1BUCIsIGdlbnVzPWdlbnVzKSRwXzFzcGVjICsgDQogIGdndGl0bGUoZ3N1YigiXyIsICIgIiwgZ2VudXMpLCBOVUxMKSArIHhsYWIoIlVNQVAgMSIpKyB5bGFiKCJVTUFQIDIiKSArIA0KICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE3KSkgKyBndWlkZXMoc2hhcGU9Im5vbmUiKSsgDQogIGxhYnMoY29sb3IgPSAicmVsYXRpdmUgXG5hYnVuZGFuY2UiKQ0KfQ0KYGBgDQoNCg0KYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTIzLCBtZXNzYWdlPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0NCndyYXBfcGxvdHMocF9saXN0LCBuY29sPTMpDQpgYGANCg0KDQpgYGB7cn0NCmdnc2F2ZSgiU3VwX0ZpZ3VyZTMucG5nIiwNCiAgICAgICB3cmFwX3Bsb3RzKHBfbGlzdCwgbmNvbD0zKSwgDQogICAgICAgd2lkdGg9MjMsIGhlaWdodD0xOCkNCmBgYA0KDQoNCg0KDQoNCiMgU3VwIEZpZ3VyZSA1OiBDaGFuZ2UgaW4gYWxwaGEgZGl2ZXJzaXR5DQoNCg0KDQpgYGB7cn0NCm1lYXN1cmVzIDwtIGMoImRicCIsICJEaXZlcmdlbmNlX3RvX21lZGlhbiIsICJMb2dfbW9kdWxvX3NrZXduZXNzIiwgIk9ic2VydmVkIiwgIlBpZWxvdSIsICJTaGFubm9uIikNCnN1YnRpdGxlIDwtIGMoIk1lYXN1cmUgb2YgRG9taW5hbmNlIiwgIk1lYXN1cmUgb2YgZGl2ZXJnZW5jZSIsICJNZWFzdXJlIG9mIHJhcml0eSIsICJNZWFzdXJlIG9mIHJpY2huZXNzIiwgIk1lYXN1cmUgb2YgRXZlbm5lc3MiLCAiTWVhc3VyZSBvZiBkaXZlcnNpdHkiKQ0KdHJhbnMgPC0gYygibG9nIiwgcmVwKCIiLCA1KSkNCg0KcHBfbGlzdCA8LSBsaXN0KCkNCmZvcihpIGluIHNlcShsZW5ndGgobWVhc3VyZXMpKSl7DQogIHBwX2xpc3RbW2ldXSA8LSBwbG90X3NhbXBsZV9tZWFzdXJlX0NPKHRzZSwgbWVhc3VyZXNbaV0sIHN1YnRpdGxlW2ldLCBjb2xvckludGVyPVQsIHRyYW5zPXRyYW5zW2ldLCBwcmludF90YWJsZT1GKSArIGdndGl0bGUoZ3N1YigiXyIsICIgIiwgbWVhc3VyZXNbaV0pKSArIHlsYWIoIiIpICsgDQogICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE0KSkNCn0NCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xNn0NCndyYXBfcGxvdHMocHBfbGlzdCwgbnJvdz0yKSANCmBgYA0KDQoNCmBgYHtyfQ0KZ2dzYXZlKCJTdXBfRmlndXJlNS5wbmciLCB3cmFwX3Bsb3RzKHBwX2xpc3QsIG5yb3c9MiksIHdpZHRoPTE2LCBoZWlnaHQgPSA4KQ0KYGBgDQoNCg0KDQoNCiAgDQojIFN1cCBGaWd1cmUgNjogQ2hhbmdlIGluIFNDRkENCg0KYGBge3J9DQpsb2FkKGZpbGU9cGFzdGUoZGlyLCAiRGF0YVByZXBhcmF0aW9uL01ldGFib2xvbWljL01ldGFib2xvbWVEYXRhLlJkYXRhIiwgc2VwPSIiKSkNCmBgYA0KDQoNCmBgYHtyfQ0KbWVhc3VyZXMgPC0gYygiQWNldGljX2FjaWQiLCAiQnV0eXJpY19hY2lkIiwgIkhleGFub2ljX2FjaWQiLCAiSXNvYnV0eXJpY19hY2lkIiwgIklzb3ZhbGVyaWNfYWNpZCIsICJNZXRoeWxidXR5cmljX2FjaWQyIiwgIlByb3Bpb25pY19hY2lkIiwgIlZhbGVyaWNfYWNpZCIpDQptZWFzdXJlc19uYW1lIDwtIGMoIkFjZXRpYyBhY2lkIiwgIkJ1dHlyaWMgYWNpZCIsICJIZXhhbm9pYyBhY2lkIiwgIklzb2J1dHlyaWMgYWNpZCIsICJJc292YWxlcmljIGFjaWQiLCAiTWV0aHlsYnV0eXJpYyBhY2lkIiwgIlByb3Bpb25pYyBhY2lkIiwgIlZhbGVyaWMgYWNpZCIpIA0KDQp0cmFucyA8LSBjKCJzcXJ0IiwgInNxcnQiLCAicHNkX2xvZyIsICJzcXJ0IiwgInNxcnQiLCAic3FydCIsICJzcXJ0IiwgInNxcnQiKQ0KbmFtZXModHJhbnMpIDwtIG1lYXN1cmVzDQoNCmBgYA0KDQoNCmBgYHtyfQ0KbGxfcGxvdCA8LSBsaXN0KCkNCmZvcihpIGluIHNlcShsZW5ndGgobWVhc3VyZXMpKSl7DQogIGxsX3Bsb3RbW2ldXSA8LSBwbG90X3NhbXBsZV9tZWFzdXJlX0NPKERBVEFfd2lkZSwgbWVhc3VyZXNbaV0sICIiLCB4PSJUcmVhdG1lbnQiLCBjb2xvckludGVyID0gVCwgcHJpbnRfdGFibGU9RiwgdHJhbnMgPSB0cmFuc1tpXSkgKyBnZ3RpdGxlKG1lYXN1cmVzX25hbWVbaV0sIHN1YnRpdGxlID0gTlVMTCkrIHlsYWIoIiIpKw0KICAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNCkpDQp9DQoNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTYsIHdhcm5pbmc9Rn0NCndyYXBfcGxvdHMobGxfcGxvdCwgbnJvdz0zKSAgKyBwbG90X2xheW91dChndWlkZXMgPSAiY29sbGVjdCIpIA0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJTdXBfRmlndXJlNi5wbmciLCB3cmFwX3Bsb3RzKGxsX3Bsb3QsIG5yb3c9MiksIHdpZHRoPTE2LCBoZWlnaHQgPSA4KQ0KYGBgDQoNCiAgDQojIFN1cCBGaWd1cmUgNzogQ2hhbmdlIGluIEJsb29kIG1hcmtlcnMNCg0KDQpgYGB7cn0NCmxvYWQocGFzdGUoZGlyLCAiRGF0YVByZXBhcmF0aW9uL0Jsb29kTWFya2Vycy9CbG9vZERhdGFfQWxsTWFya2Vycy5SZGF0YSIsIHNlcD0iIikpDQpgYGANCg0KDQpgYGB7cn0NCm1lYXN1cmVzIDwtIGMoIlNDUlAiLCAiSUw2IiwgIlRORlIyIiwgIkZSVUMiLCAiUkFHRSIsICI4T0hkRyIsICJ6b251bGluIikgDQptZWFzdXJlc19uYW1lIDwtIGMoIkNSUCIsICJJbnRlcmxldWtpbi02IiwgIlRORlIyIiwgIkZydWN0b3NhbWluZSIsICJzUkFHRSIsICI4LU9IZEciLCAiWm9udWxpbiIpIA0KDQp0cmFucyA8LSBjKCJsb2ciLCAibG9nIiwgImxvZyIsICJsb2ciLCAiIiwgIiIsICIiKQ0KbmFtZXModHJhbnMpIDwtIG1lYXN1cmVzDQpgYGANCg0KYGBge3J9DQpsbF9wbG90IDwtIGxpc3QoKQ0KZm9yKGkgaW4gc2VxKGxlbmd0aChtZWFzdXJlcykpKXsNCiAgbGxfcGxvdFtbaV1dIDwtIHBsb3Rfc2FtcGxlX21lYXN1cmVfQ08oZGF0YV9tZXJnZWQsIG1lYXN1cmVzW2ldLCAiIiwgeD0iVHJlYXRtZW50IiwgY29sb3JJbnRlciA9IFQsIHByaW50X3RhYmxlPUYsIHRyYW5zID0gdHJhbnNbaV0pICsgZ2d0aXRsZShtZWFzdXJlc19uYW1lW2ldLCBzdWJ0aXRsZSA9IE5VTEwpKyB5bGFiKCIiKSsNCiAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpKQ0KfQ0KDQpgYGANCg0KYGBge3IgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE2LCB3YXJuaW5nPUZ9DQp3cmFwX3Bsb3RzKGxsX3Bsb3QsIG5yb3c9MykgICsgcGxvdF9sYXlvdXQoZ3VpZGVzID0gImNvbGxlY3QiKSANCmBgYA0KDQoNCmBgYHtyfQ0KZ2dzYXZlKCJTdXBfRmlndXJlNy5wbmciLCB3cmFwX3Bsb3RzKGxsX3Bsb3QsIG5yb3c9MyksIHdpZHRoPTE2LCBoZWlnaHQgPSAxMikNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K